﻿#include "PLCServerBase.h"
#pragma execution_character_set("utf-8")

QMap<ComState, QString> PLCServerBase::mapPLCServerStateText{};
QMap<PLCServerType, QString> PLCServerBase::mapPLCServerTypeText = {{PST_ModbusTcp, "PST_ModbusTcp"},
                                                                    {PST_ModbusRtu, "PST_ModbusRtu"}};
PLCServerBase::PLCServerBase(QObject *parent)
    : QObject{parent}
{

#if QT_VERSION >= 0x060000
// Qt 6 的代码
#else
    // Qt 5 的代码
    qRegisterMetaTypeStreamOperators<SerialComConfig>("SerialComConfig");//注册结构体的操作流,就是重写的输入输出流
    qRegisterMetaTypeStreamOperators<TcpComConfig>("TcpClientConfig");//注册结构体的操作流,就是重写的输入输出流
    qRegisterMetaTypeStreamOperators<PLCServerConfig>("PLCServerConfig&");
#endif
    qRegisterMetaType<SerialComConfig>("SerialComConfig");
    qRegisterMetaType<SerialComConfig>("SerialComConfig&");

    qRegisterMetaType<TcpComConfig>("TcpClientConfig");
    qRegisterMetaType<TcpComConfig>("TcpClientConfig&");

    qRegisterMetaType<PLCRequestData>("PLCRequestData");
    qRegisterMetaType<PLCRequestData>("PLCRequestData&");

    qRegisterMetaType<PLCServerConfig>("PLCServerConfig");
    qRegisterMetaType<ComState>("ComState");
    qRegisterMetaType<QModbusDataUnit::RegisterType>("QModbusDataUnit::RegisterType");
    qRegisterMetaType<QModbusDataUnit::RegisterType>("QModbusDataUnit::RegisterType&");

    setServerState(CS_Invalid);
    mapPLCServerStateText = {{CS_Invalid,tr("<font color=\'red\'>不可用</font>")},
                             {CS_Connected,tr("<font color=\'green\'>连接成功</font>")},
                             {CS_UnConnected,tr("<font color=\'yellow\'>服务端打开</font>")}};




}

void PLCServerBase::onInit()
{
    bool isConnected = false;
    QModbusDataUnit coilDataNow = coilDataPre;
    QModbusDataUnit holdDataNow = holdDataPre;
    QModbusDataUnit discreDataNow = discreDataPre;
    QModbusDataUnit inputDataNow = inputDataPre;
    if(mServer->state() == QModbusDevice::ConnectedState){
        isConnected = true;
        mServer->data(&coilDataNow);
        mServer->data(&holdDataNow);
        mServer->data(&discreDataNow);
        mServer->data(&inputDataNow);
    }
    initCom();
    if(isConnected){
        mServer->setData(coilDataNow);
        mServer->setData(holdDataNow);
        mServer->setData(discreDataNow);
        mServer->setData(inputDataNow);
    }
}

void PLCServerBase::onQuit()
{
    if(mServer->state() == QModbusDevice::ConnectedState){
        mServer->disconnect();
    }
    if(mServer != nullptr){
        mServer->deleteLater();
        mServer = nullptr;
    }
}
void PLCServerBase::onPLCConfigChanged(const PLCServerConfig &plcConfig)
{
    if(plcConfig.name != mConfig.name)
        return;
    mConfig = plcConfig;
    onInit();
}

void PLCServerBase::setupDeviceData()
{

}
void PLCServerBase::onWrite(const PLCRequestData& requestData)
{
    for(auto value : requestData.data){
        QVector<quint16> data;
        if(value.valueType == VT_Int16 || value.valueType == VT_Bool){
            data.push_back(value.valueI);
        } else if(value.valueType == VT_Int32){
            int16_t val1, val2;
            int32ToInt16(value.valueDI, val1, val2);
            data.push_back(val1);
            data.push_back(val2);
        } else if(value.valueType == VT_Float){
            QList<qint16> lstData = float2int16(value.valueF);
            for(auto val : lstData){
                data.push_back(val);
            }
        }
        QModbusDataUnit dataUnit(requestData.table, requestData.addrStart + value.addr, data);
        writeData(dataUnit);
    }
}

void PLCServerBase::onRead(const PLCRequestData &requestData)
{
    PLCRequestData dataResult = requestData;
    QList<ModbusValue> valueList = dataResult.data;
    for (int i = 0; i < valueList.size(); ++i) {
        ModbusValue modbusValue = valueList.at(i);
        if(modbusValue.valueType == VT_Int16 || modbusValue.valueType == VT_Bool){
            quint16 value = 0;
            mServer->data(dataResult.table, dataResult.addrStart + modbusValue.addr, &value);
            modbusValue.valueI = value;
        } else if(modbusValue.valueType == VT_Int32){
            quint16 value = 0, value1 = 0;
            mServer->data(dataResult.table, dataResult.addrStart + modbusValue.addr, &value);
            mServer->data(dataResult.table, dataResult.addrStart + modbusValue.addr + 1, &value1);
            modbusValue.valueDI = int162int32(value, value1);
        } else if(modbusValue.valueType == VT_Float){
            quint16 value = 0, value1 = 0;
            mServer->data(dataResult.table, dataResult.addrStart + modbusValue.addr, &value);
            mServer->data(dataResult.table, dataResult.addrStart + modbusValue.addr + 1, &value1);
            modbusValue.valueF = int162float(value, value1);
        }
        valueList[i] = modbusValue;
    }
    dataResult.data = valueList;
    emit sigData(dataResult);
}

void PLCServerBase::setServerState(ComState state)
{
    if(mPLCState == state)
        return;
    mPLCState = state;
    emit sigStateChanged(mPLCState);
}

void PLCServerBase::readData(QModbusDataUnit::RegisterType table, int address, int size)
{
    PLCRequestData requestData;

    QList<ModbusValue> valueList;
    for (int i = 0; i < size; ++i) {
        ModbusValue modbusValue;
        quint16 value=0;
        mServer->data(table, address + i, &value);
        modbusValue.addr = i;
        modbusValue.valueI = value;
        modbusValue.valueType = VT_Int16;
        valueList.push_back(modbusValue);
    }
    requestData.table = table;
    requestData.addrStart = address;
    requestData.data = valueList;
    processData(requestData);
    emit sigData(requestData);
}

void PLCServerBase::writeData(const QModbusDataUnit &newData)
{
    if (!mServer)
        return;
    bool ok  = mServer->setData(newData);
    if (!ok){
        emit sigErrOccur(tr("发送PLC失败: ") + mServer->errorString());
    }
}
